﻿//========================================================= 
/**@file DevPBOC_CmdDriver.h
 * @brief 将PBOC命令集成到设备的命令驱动
 * 
 * @date 2016-11-11   21:11:33
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_DEVPBOC_CMDDRIVER_H_
#define _LIBZHOUYB_DEVPBOC_CMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"

#include "../../device/PBOC_ReaderDevAdapter.h"
using zhou_yb::application::device::PBOC_ReaderDevAdapter;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/// 设备内部集成PBOC功能命令驱动
class DevPBOC_CmdDriver :
    public CommonCmdDriver,
    public BaseDevAdapterBehavior<IInteractiveTrans>
{
protected:
    ComICCardCmdAdapter _cmdAdapter;
    PBOC_ReaderDevAdapter _readerAdapter;
public:
    DevPBOC_CmdDriver() : CommonCmdDriver()
    {
        _errGetter.Add(_readerAdapter)
            .Select("IC_CMD", _cmdAdapter);

        select_helper<LoggerSetter::SelecterType>::select(_logSetter),
            _cmdAdapter, _readerAdapter;
        _readerAdapter.SelectDevice(_cmdAdapter);

        Ref<ComplexCommand> transformSlotCMD = _RegisteCMD(DevPBOC_CmdDriver, TransformSLOT);
        _RegisteCMD(DevPBOC_CmdDriver, GetCardNumber)->PrefixBind(transformSlotCMD);
        _RegisteCMD(DevPBOC_CmdDriver, ReadTAG)->PrefixBind(transformSlotCMD);
        _RegisteExceptCMD(DevPBOC_CmdDriver);
        _RegisteAdapterCMD(DevPBOC_CmdDriver);
    }
    LC_CMD_EXCEPT()
    {
        EXCEPT_CMD(TransformSLOT);
        return true;
    }
    LC_CMD_ADAPTER_INVOKE(IInteractiveTrans, _cmdAdapter);
    /**
     * @brief 
     * @date 2017-07-19 14:03
     * 
     * @param SLOT : string 字符串类型的卡槽
     * - 卡槽:
     *  - Contact : 0x00 接触式卡槽
     *  - Contactless : 0xFF 非接触卡槽
     * .
     * 
     * @retval SLOT : byte 数字类型的卡槽
     */
    LC_CMD_METHOD(TransformSLOT)
    {
        string slot;
        if(!arg.Get("SLOT", slot))
        {
            arg.Put("SLOT", "00");
            return true;
        }
        ByteArray slotArray(slot.c_str());
        IStringArguments::ArgType& argVal = arg["SLOT"];
        if(StringConvert::Compare("CONTACTLESS", slotArray, true))
        {
            argVal.Value = "FF";
        }
        else if(StringConvert::Compare("CONTACT", slotArray, true))
        {
            argVal.Value = "00";
        }
        return true;
    }
    /**
     * @brief 获取卡号
     * @date 2017-04-20 22:38
     * 
     * @param [in] SLOT : byte [default:0x00] 需要操作的卡槽
     * - 卡槽:
     *  - 0x00 : 接触 Contact
     *  - 0xFF : 非接 Contactless
     * .
     * 
     * @retval CardNumber : string 获取到的卡号
     */
    LC_CMD_METHOD(GetCardNumber)
    {
        byte slot = arg["SLOT"].To<byte>(0x00);
        ByteBuilder cardNumber(16);
        ASSERT_FuncErrInfo(_readerAdapter.GetCardNumber(slot, cardNumber),
            DeviceError::OperatorErr, "获取卡号失败");
        rlt.Put("CardNumber", cardNumber.GetString());
        return true;
    }
    /**
     * @brief 通过GPO_Token获取IC卡标签数据
     * @date 2017-04-20 22:42
     * 
     * @param [in] SLOT : byte 需要操作的卡槽
     * @param [in] GPO_Token : hex GPO命令后返回的Token信息
     * @param [in] TAG : hex 需要读取的IC卡标签
     * @param [in] IsAssertTAG : bool [default:true] 是否强制校验读完全部标签
     * 
     * @retval TLV : hex 获取到的IC卡TLV信息
     */
    LC_CMD_METHOD(ReadTAG)
    {
        string sGpo;
        if(!arg.Get("GPO_Token", sGpo))
        {
            _logErr(DeviceError::ArgErr, "缺少参数:[GPO_Token]");
            return false;
        }
        byte slot = arg["SLOT"].To<byte>(0x00);
        ByteBuilder gpo(8);
        DevCommand::FromAscii(sGpo.c_str(), gpo);

        GPO_Token gpoToken;
        PBOC_Library::TagToGPO_Token(gpo, gpoToken);

        string sTag = arg["TAG"].To<string>("");
        ByteBuilder tagHex(16);
        DevCommand::FromAscii(sTag.c_str(), tagHex);
        ByteBuilder appData(64);

        list_t<TlvHeader> taglist;
        PBOC_Library::MakeTagList(tagHex, taglist);
        size_t count = PBOC_Library::SelectTagToBuffer(taglist, gpo, appData);
        // 还有标签未找到
        if(count < taglist.size())
        {
            ASSERT_FuncErrInfo(_readerAdapter.GetInformation(slot, gpoToken, tagHex, appData),
                DeviceError::OperatorErr, "设备内部执行PBOC失败");
        }
        ByteBuilder tmp(64);
        ByteConvert::ToAscii(appData, tmp);
        rlt.Put("TLV", tmp.GetString());

        if(arg["IsAssertTAG"].To<bool>(true))
        {
            TlvElement tlv;
            TlvElement::Parse(tlv, appData);
            if(tlv.GetCount() < taglist.size())
            {
                _logErr(DeviceError::ArgCountErr, "读标签缺失");
                return false;
            }
        }
        return true;
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_DEVPBOC_CMDDRIVER_H_
//========================================================= 